// Copyright  2004-2008 Backplane Ltd.
//
// This file is part of Ubiquity formsPlayer
//
// Ubiquity formsPlayer is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3 of the License, or (at your
// option) any later version.
//
// Ubiquity formsPlayer is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License
// along with Ubiquity formsPlayer If not, see <http://www.gnu.org/licenses/>.
//	
//
//   Purpose: implementation of CImplChoices.
//   $Id$



#include "stdafx.h"
#include "choices.h"

#include "xforms.h"
#include "model.h"
#include "SelectUI.h"
#include "xformsxformselement.h"

#include "boundnode.h"
#include "commonchild.h"


CImplChoices::CImplChoices()
	:m_pCaption(0)
{
	
}

CImplChoices::~CImplChoices()
{

	if(m_pCaption)
		m_pCaption->m_pParent = 0;
	/*
	 * Delete any items
	 */
	while(!m_Items.IsEmpty())
	{
		CFormControl * pFc = dynamic_cast<CFormControl*>(m_Items.RemoveHead());
		if(pFc)
		{
			pFc->m_pParentImpl = 0;
			pFc->RequestDeleteAtEarliestConvenience();
		}
	}

	if(m_pParent)
	{
		CImplSelection * pSel = dynamic_cast<CImplSelection *>(m_pParent);
		if(pSel)
			pSel->RemoveItem(this);
		else
		{
			CImplChoices * pChoices = dynamic_cast<CImplChoices *>(m_pParent);
			if(pChoices)
			{
				pChoices->RemoveItem(this);
			}
		}
	}

}


HRESULT CImplChoices::onCaptionValueChange(BSTR sCaption)
{
#ifdef OLD_SELECT_METHOD
	CImplSelection * pOwner = GetOwnerSelection();
	if(pOwner)
	{
		pOwner->checkDrawn();

		return ((CXFormsElementSelection * )pOwner->m_pXFormsElement)
			->put_ItemCaption(m_sId,sCaption);
	}
	return E_FAIL;
#else
	m_pResolvedItem->put_label(sCaption);
	return S_OK;
#endif
}


HRESULT CImplChoices::draw(BSTR const sDrawInside)
{
	HRESULT hr = E_FAIL;
	
	
	//	insert an element for the choices group ... 
	CImplSelection * pSel = GetOwnerSelection();
	if(pSel)
	{
		BSTR bs = ::SysAllocString(L" ");
		hr = GetOwnerSelection()->drawItem(this, m_sId.m_str, bs, m_sId.m_str, sDrawInside, true);
		::SysFreeString(bs);
		
		/*CComBSTR s;
			m_pCaption->GetMultipleTextSource(&s);
		
			hr = GetOwnerSelection()->drawItem(this, m_sId.m_str, s, m_sId.m_str, sDrawInside, true);
		*/
		
		if(SUCCEEDED(hr))
		{
			// and call draw on all items.
			POSITION pos = m_Items.GetHeadPosition();
			while(pos)
			{
				m_Items.GetNext(pos)->draw(m_sId.m_str);
			}
		}
	}
	return hr;
}

void CImplChoices::AddItem(ISelectionChild* pItem)
{
	m_Items.AddTail(pItem);
}



void CImplChoices::RemoveItem(ISelectionChild * pItem)
{
	//used in the destruction of children	
	POSITION pos = m_Items.Find(pItem);
	if(pos)
		m_Items.RemoveAt(pos);
	//allows the owner selection to remove it
	//	if it is a dependent control.
	GetOwnerSelection()->RemoveItem(pItem);
}

HRESULT CImplChoices::init(CImpl * pParent)
{
	if(!m_sId || m_sId == L"")
	{
		m_sId.Empty();

		//must have an id for internal purposes,
		//	it is not an error for this to be without 
		//	an id.
		//Generate an ID from the "this" pointer
		wchar_t sBuff[11];
		swprintf(sBuff,L"%X",(long)this);
		m_sId = sBuff;
		// m_sId = CComBSTR(sBuff); // This results in the location of memory twice.
	}
	HRESULT hr = CFormControl::init(pParent);
	return hr;
}


HRESULT CImplChoices::detachCaption(void)
{
	m_pCaption = 0;
	return S_OK;
}

void CImplChoices::CreateResolvedCounterpart()
{
	//choices is the same as item, choices maintains a one-to-one
	//	relationship between itself and a single resolved item,
	//	however, it also has children, these are the value of 
	//	the resolved item.
	CResolvedItemList * pList = dynamic_cast<IResolvedItemContainer*>(m_pParent)->GetResolvedItemList();
	if(pList)
	{
		m_pResolvedItem = pList->InsertNewItem(0,m_lIx);
		m_pResolvedItem->put_value(&m_ResolvedItems);
	}
}

void CImplChoices::SetSelectionIndex(long lIndex)
{
	m_lIx = lIndex;
}



void CImplChoices::deselect()
{
	//Do Nothing
}

void CImplChoices::select(const long lIndex)
{
	//TODO: selecting a choices should select
	//	the children of choices.
	//ASSERT(false && E_NOTIMPL);
}

void CImplChoices::selectFrom(CList<VARIANT, VARIANT> &lstValues, CStringW &sList)
{
	POSITION pos = m_Items.GetHeadPosition();
	while(pos && !lstValues.IsEmpty())
	{
		m_Items.GetNext(pos)->selectFrom(lstValues,sList);
	}
}
CResolvedItemList * CImplChoices::GetResolvedItemList()
{
	return &m_ResolvedItems;
}

CImplSelection * CImplChoices::GetOwnerSelection()
{
	ISelectionChild * pParent = dynamic_cast<ISelectionChild*>(m_pParent);
	if(pParent)
	{
		return pParent->GetOwnerSelection();
	}
	else
	{
		return static_cast<CImplSelection *>(m_pParent);
	}
}


